package org.jeecg.modules.demo.weixin.refundrecord.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.demo.api.UpmsHelloApi;
import org.jeecg.modules.demo.entity.Dept;
import org.jeecg.modules.demo.mall.api.MallHelloApi;
import org.jeecg.modules.demo.weixin.dto.RefundDto;
import org.jeecg.modules.demo.weixin.entity.MerchantPay;
import org.jeecg.modules.demo.weixin.entity.PayOrder;
import org.jeecg.modules.demo.weixin.entity.RefundRecord;
import org.jeecg.modules.demo.weixin.merchantpay.service.IMerchantPayService;
import org.jeecg.modules.demo.weixin.payorder.service.IPayOrderService;
import org.jeecg.modules.demo.weixin.refundrecord.mapper.RefundRecordMapper;
import org.jeecg.modules.demo.weixin.refundrecord.service.IRefundRecordService;
import org.jeecg.modules.demo.weixin.smtstoreduserpoint.service.ISmtStoredUserPointService;
import org.jeecg.modules.demo.weixin.util.PayConstants;
import org.jeecg.modules.demo.weixin.util.WeChatUtil;
import org.jeecg.modules.demo.weixin.util.ZhiFuBaoUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 退款记录表
 * @Author: jeecg-boot
 * @Date: 2023-11-02
 * @Version: V1.0
 */
@Service
public class RefundRecordServiceImpl extends ServiceImpl<RefundRecordMapper, RefundRecord> implements IRefundRecordService {

    @Autowired
    private IMerchantPayService merchantPayService;
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private MallHelloApi mallHelloApi;

    @Autowired
    private ISmtStoredUserPointService smtStoredUserPointService;
    @Autowired
    private   UpmsHelloApi upmsHelloApi;


    /**
     * 退款接口
     *
     * @param refundDto
     * @return
     */
    @SneakyThrows
    @Override
    public Map<String, String> refund(RefundDto refundDto, String refundId) {

        PayOrder payOrder = payOrderService.getById(refundDto.getOutTradeNo());
        //根据商家id查询商家配置的支付信息
        QueryWrapper<MerchantPay> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", Integer.valueOf(refundDto.getMerId()));
        MerchantPay merchantPay = merchantPayService.getOne(queryWrapper);

        //微信支付的单位是分，要转换一下
        String amount = String.valueOf(refundDto.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue());
        //微信退款金额的单位是分，要转换一下
        String refundAmount = String.valueOf(refundDto.getRefundPrice().multiply(BigDecimal.valueOf(100)).intValue());
        //生成随机数
        String nonceStr = WXPayUtil.generateNonceStr();
        //格式化返回数据
        Map<String, String> jsonParams = new HashMap<>();
        jsonParams.put("appid", PayConstants.App_ID_SERVICE);
        jsonParams.put("mch_id", PayConstants.MCH_ID_SERVICE);
        jsonParams.put("sub_mch_id", merchantPay.getSpecialSubMerchants());
        jsonParams.put("nonce_str", nonceStr);
        jsonParams.put("transaction_id", refundDto.getTransactionId());
        jsonParams.put("out_refund_no", refundId);
        jsonParams.put("total_fee", amount);
        jsonParams.put("refund_fee", refundAmount);

        //生成签名
        String sign = WXPayUtil.generateSignature(jsonParams, PayConstants.API_V2KEY_SERVICE);
        jsonParams.put("sign", sign);

        //转为xml字符串
        String requestXmlString = WXPayUtil.mapToXml(jsonParams);
        //退款url
        String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        // 发送退款请求
        HttpResponse resp = WeChatUtil.httpPost(refundUrl, requestXmlString, merchantPay, payOrder.getMerchantType());
        String entityStr = EntityUtils.toString(resp.getEntity(), "UTF-8");
        //转为map并返回
        return WXPayUtil.xmlToMap(entityStr);
    }

    /**
     * 退款接口(服务商)
     *
     * @param refundDto
     * @return
     */
    @SneakyThrows
    @Override
    public Map<String, String> serviceRefund(RefundDto refundDto, String refundId) {
        PayOrder payOrder = payOrderService.getById(refundDto.getOutTradeNo());
        //根据商家id查询商家配置的支付信息
        QueryWrapper<MerchantPay> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", refundDto.getMerId());
        MerchantPay merchantPay = merchantPayService.getOne(queryWrapper);

        //微信支付的单位是分，要转换一下
        String amount = String.valueOf(refundDto.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue());
        //微信退款金额的单位是分，要转换一下
        String refundAmount = String.valueOf(refundDto.getRefundPrice().multiply(BigDecimal.valueOf(100)).intValue());
        //生成随机数
        String nonceStr = WXPayUtil.generateNonceStr();
        //格式化返回数据
        Map<String, String> jsonParams = new HashMap<>();
        jsonParams.put("appid", PayConstants.App_ID_SERVICE);
        jsonParams.put("mch_id", PayConstants.MCH_ID_SERVICE);
        jsonParams.put("sub_mch_id", merchantPay.getMchId());
        jsonParams.put("nonce_str", nonceStr);
        jsonParams.put("transaction_id", refundDto.getTransactionId());
        jsonParams.put("out_refund_no", refundId);
        jsonParams.put("total_fee", amount);
        jsonParams.put("refund_fee", refundAmount);

        //生成签名
        String sign = WXPayUtil.generateSignature(jsonParams, PayConstants.API_V2KEY_SERVICE);
        jsonParams.put("sign", sign);

        //转为xml字符串
        String requestXmlString = WXPayUtil.mapToXml(jsonParams);
        //退款url
        String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        // 发送退款请求
        HttpResponse resp = WeChatUtil.httpPost(refundUrl, requestXmlString, merchantPay, payOrder.getMerchantType());
        String entityStr = EntityUtils.toString(resp.getEntity(), "UTF-8");
        //转为map并返回
        return WXPayUtil.xmlToMap(entityStr);
    }

    /**
     * 根据订单状态退款
     *
     * @param refundDto
     * @param payOrder
     * @return
     */
    @Override
    public Result<?> refundByOrderType(RefundDto refundDto, PayOrder payOrder, RefundRecord refundRecord) {
        //如果是余额支付则退回余额
        if (payOrder.getBalancePay().compareTo(BigDecimal.valueOf(0)) > 0 && payOrder.getPayPrice().compareTo(BigDecimal.valueOf(0)) == 0
                && payOrder.getCashPay().compareTo(BigDecimal.valueOf(0)) == 0) {
            //生成退款记录
            BeanUtils.copyProperties(refundDto, refundRecord);
            refundRecord.setTotalFee(refundDto.getTotalPrice());
            refundRecord.setRefundStatus(2);
            refundRecord.setMerId(Integer.valueOf(payOrder.getMerchantId()));

            if (refundDto.getBalancePay().compareTo(payOrder.getBalancePay()) > 0) {
                return Result.error(606, "退款金额大于支付金额");
            }
            refundRecord.setRefundFee(refundDto.getBalancePay());
            this.save(refundRecord);

//            YxUser yxUser = new YxUser();
//            yxUser.setUid(payOrder.getUserId());
//            yxUser.setRefundBalance(payOrder.getBalancePay());
//            mallHelloApi.updateAmount(yxUser);
            //处理订单逻辑
            Result<?> result = payOrderService.updateOrder(refundRecord);
            if (result.getCode() != 200) {
                return Result.error(606, result.getMessage());
            }
            return Result.OK("余额退款成功！");
        }
        //如果是现金支付直接修改状态
        if (payOrder.getCashPay().compareTo(BigDecimal.valueOf(0)) > 0 && payOrder.getPayPrice().compareTo(BigDecimal.valueOf(0)) == 0
                && payOrder.getBalancePay().compareTo(BigDecimal.valueOf(0)) == 0) {

            //如果是储值订单退款需要减掉充值的余额
            if (payOrder.getOrderType() == 1) {
                BigDecimal bigDecimal = smtStoredUserPointService.subPoint(payOrder.getTotalPrice(), payOrder.getGivePrice(), payOrder.getUserId(), String.valueOf(refundDto.getMerId()), payOrder.getOrderNo());
                if (bigDecimal == null) {
                    return Result.error(606, "用户卡点状态不支持退款");
                }
                refundRecord.setRefundFee(bigDecimal);
            } else {
                refundRecord.setRefundFee(refundDto.getCashPay());
            }
            //生成退款记录
            BeanUtils.copyProperties(refundDto, refundRecord);
            refundRecord.setTotalFee(refundDto.getTotalPrice());
            refundRecord.setRefundStatus(2);
            refundRecord.setMerId(Integer.valueOf(payOrder.getMerchantId()));
            this.save(refundRecord);

            //处理订单逻辑
            Result<?> result = payOrderService.updateOrder(refundRecord);
            if (result.getCode() != 200) {
                return Result.error(606, result.getMessage());
            }
            return Result.OK("现金退款成功！");
        }
        //如果是现金和余额支付直接修改状态
        if (payOrder.getCashPay().compareTo(BigDecimal.valueOf(0)) > 0 && payOrder.getPayPrice().compareTo(BigDecimal.valueOf(0)) == 0
                && payOrder.getBalancePay().compareTo(BigDecimal.valueOf(0)) > 0) {
            //生成退款记录
            BeanUtils.copyProperties(refundDto, refundRecord);
            refundRecord.setTotalFee(refundDto.getTotalPrice());
            refundRecord.setRefundStatus(2);
            refundRecord.setMerId(Integer.valueOf(payOrder.getMerchantId()));
            refundRecord.setRefundFee(refundDto.getTotalPrice());
            this.save(refundRecord);

//            YxUser yxUser = new YxUser();
//            yxUser.setUid(payOrder.getUserId());
//            yxUser.setNowMoney(payOrder.getBalancePay());
//            mallHelloApi.subBalance(yxUser);
            //处理订单逻辑
            Result<?> result = payOrderService.updateOrder(refundRecord);
            if (result.getCode() != 200) {
                return Result.error(606, result.getMessage());
            }
            return Result.OK("现金余额组合支付退款成功！");
        }
        //零元退款时
//        if (payOrder.getActualPrice() != null && payOrder.getIsCoupon().equals(0)) {
        if (payOrder.getActualPrice() != null && payOrder.getActualPrice().compareTo(BigDecimal.ZERO) == 0) {
            BeanUtils.copyProperties(refundDto, refundRecord);
            refundRecord.setTotalFee(payOrder.getActualPrice());
            refundRecord.setRefundStatus(2);
            refundRecord.setMerId(Integer.valueOf(payOrder.getMerchantId()));
            refundRecord.setRefundFee(refundDto.getTotalPrice());
            this.save(refundRecord);
            Result<?> result = payOrderService.updateOrder(refundRecord);
            if (result.getCode() != 200) {
                return Result.error(606, result.getMessage());
            }
            return Result.OK("零元支付退款成功！");
        }
        return Result.error(608, "未匹配到退款订单！");
    }
    @SneakyThrows
    @Override
    public Result<?> refundZfb(RefundDto refundDto, String refundId,RefundRecord refundRecord) {
        Dept dept = upmsHelloApi.queryByDept(Long.valueOf(refundDto.getMerId()));
        if (dept==null){
            return Result.error("门店信息不存在!");
        }
        if (StringUtils.isBlank(dept.getZfbMerId()) && StringUtils.isBlank(dept.getZfbToken())) {
            return Result.error("请先配置支付宝商家支付信息！");
        }
        String outRequestNo = System.nanoTime() + RandomUtil.randomString(3);
        AlipayTradeRefundResponse alipayTradeRefundResponse = ZhiFuBaoUtils.zhifubTk(outRequestNo, refundId, dept.getZfbToken(), String.valueOf(refundDto.getPayPrice()));
        if (alipayTradeRefundResponse==null){
            return Result.error("退款失败！");
        }
        Thread.sleep(10000);
        AlipayTradeFastpayRefundQueryResponse tkCx = ZhiFuBaoUtils.tkCx(outRequestNo, refundId, dept.getZfbToken());
        if (tkCx==null){
            return Result.error("订单信息不存在！");
        }
        if (tkCx.getRefundStatus()==null){
            return Result.error("退款失败！");
        }
        if (tkCx.getRefundStatus().equals("REFUND_SUCCESS")){
            BeanUtils.copyProperties(refundDto, refundRecord);
            refundRecord.setTotalFee(refundDto.getTotalPrice());
            refundRecord.setRefundFee(refundDto.getRefundPrice());
            refundRecord.setRefundId(outRequestNo);
            refundRecord.setMchId(dept.getZfbMerId());
            refundRecord.setRefundStatus(2);
            this.save(refundRecord);

            //处理订单逻辑
            Result<?> result = payOrderService.updateOrder(refundRecord);
            if (result.getCode() != 200) {
                return Result.error(606, result.getMessage());
            }
            return Result.ok("退款成功！");
        }
        return Result.error(606,alipayTradeRefundResponse.getSubMsg());
    }
}
